%option noyywrap

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "parse_tree.h"
#include "syntax_analyzer.h"

int lines = 1;
int pos_start = 1;
int pos_end = 1;
char token_name[20];

void new_node(char *text) {
    yylval.node = new_parse_tree_node(text);
}

void update(int len) {
    pos_start = pos_end;
    pos_end += len;
}

%}

%%
"int"           {update(3); strcpy(token_name, "INT"); new_node(yytext); return INT;}
"float"         {update(5); strcpy(token_name, "FLOAT"); new_node(yytext); return FLOAT;}
"void"          {update(4); strcpy(token_name, "VOID"); new_node(yytext); return VOID;}
";"             {update(1); strcpy(token_name, "SEMICOLON"); new_node(yytext); return SEMICOLON;}
","             {update(1); strcpy(token_name, "COMMA"); new_node(yytext); return COMMA;}
"="             {update(1); strcpy(token_name, "ASSIGN"); new_node(yytext); return ASSIGN;}
"<"             {update(1); strcpy(token_name, "LT"); new_node(yytext); return LT;}
"<="            {update(2); strcpy(token_name, "LET"); new_node(yytext); return LET;}
">"             {update(1); strcpy(token_name, "GT"); new_node(yytext); return GT;}
">="            {update(2); strcpy(token_name, "GET"); new_node(yytext); return GET;}
"=="            {update(2); strcpy(token_name, "EQ"); new_node(yytext); return EQ;}
"!="            {update(2); strcpy(token_name, "NEQ"); new_node(yytext); return NEQ;}
"+"             {update(1); strcpy(token_name, "ADD"); new_node(yytext); return ADD;}
"-"             {update(1); strcpy(token_name, "SUB"); new_node(yytext); return SUB;}
"*"             {update(1); strcpy(token_name, "MUL"); new_node(yytext); return MUL;}
"/"             {update(1); strcpy(token_name, "DIV"); new_node(yytext); return DIV;}
"%"             {update(1); strcpy(token_name, "MOD"); new_node(yytext); return MOD;}
"&&"            {update(2); strcpy(token_name, "AND"); new_node(yytext); return AND;}
"||"            {update(2); strcpy(token_name, "OR"); new_node(yytext); return OR;}
"!"             {update(1); strcpy(token_name, "NOT"); new_node(yytext); return NOT;}
"("             {update(1); strcpy(token_name, "LPARENTHESIS"); new_node(yytext); return LPARENTHESIS;}
")"             {update(1); strcpy(token_name, "RPARENTHESIS"); new_node(yytext); return RPARENTHESIS;}
"["             {update(1); strcpy(token_name, "LBRACKET"); new_node(yytext); return LBRACKET;}
"]"             {update(1); strcpy(token_name, "RBRACKET"); new_node(yytext); return RBRACKET;}
"{"             {update(1); strcpy(token_name, "LBRACE"); new_node(yytext); return LBRACE;}
"}"             {update(1); strcpy(token_name, "RBRACE"); new_node(yytext); return RBRACE;}
"return"        {update(6); strcpy(token_name, "RETURN"); new_node(yytext); return RETURN;}
"if"            {update(2); strcpy(token_name, "IF"); new_node(yytext); return IF;}
"else"          {update(4); strcpy(token_name, "ELSE"); new_node(yytext); return ELSE;}
"while"         {update(5); strcpy(token_name, "WHILE"); new_node(yytext); return WHILE;}
"break"         {update(5); strcpy(token_name, "BREAK"); new_node(yytext); return BREAK;}
"continue"      {update(8); strcpy(token_name, "CONTINUE"); new_node(yytext); return CONTINUE;}
"const"         {update(5); strcpy(token_name, "CONST"); new_node(yytext); return CONST;}
[a-zA-Z_][a-zA-Z0-9_]* {update(yyleng); strcpy(token_name, "IDENT"); new_node(yytext); return IDENT;}
[0-9]+          {update(yyleng); strcpy(token_name, "INTCONST"); new_node(yytext); return INTCONST;}
0[xX][0-9a-fA-F]+ {
    update(yyleng);
    strcpy(token_name, "INTCONST");
    new_node(yytext);
    return INTCONST;
}
([0-9]*\.[0-9]+|[0-9]+\.)([eE][+-]?[0-9]+)? {
    update(yyleng);
    strcpy(token_name, "FLOATCONST");
    new_node(yytext);
    return FLOATCONST;
}
([0-9]+[eE][+-]?[0-9]+) {
    update(yyleng);
    strcpy(token_name, "FLOATCONST");
    new_node(yytext);
    return FLOATCONST;
}
0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*[pP][+-]?[0-9]+[fFlL]? {
    pos_start = pos_end;
    pos_end += yyleng;
    strcpy(token_name, "FLOATCONST");
    new_node(yytext);
    return FLOATCONST;
}

0[xX]\.[0-9a-fA-F]+[pP][+-]?[0-9]+[fFlL]? {
    pos_start = pos_end;
    pos_end += yyleng;
    strcpy(token_name, "FLOATCONST");
    new_node(yytext);
    return FLOATCONST;
}

0[xX][0-9a-fA-F]+[pP][+-]?[0-9]+[fFlL]? {
    pos_start = pos_end;
    pos_end += yyleng;
    strcpy(token_name, "FLOATCONST");
    new_node(yytext);
    return FLOATCONST;
}

"//".*          {
    update(yyleng);
    for (int i = 0; i < yyleng; i++) {
        if (yytext[i] == '\n') {
            pos_start = 1;
            pos_end = 1;
            lines += 1;
        }
    }
    /* 忽略单行注释 */
}
"/*"([^*]|\*+[^*/])*\*+"/" {
    update(yyleng);
    for (int i = 0; i < yyleng; i++) {
        if (yytext[i] == '\n') {
            pos_start = 1;
            pos_end = 1;
            lines += 1;
        }
    }
}
[ \t]           {update(1);}
\n              {
    pos_start = 1;
    pos_end = 1;
    lines += 1;
}
\r\n             {
    pos_start = 1;
    pos_end = 1;
    lines += 1;
}
%%
